﻿
using System;
using System.ComponentModel;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Linq;
using Library.WebControls.Ds;
using Library.WebControls.SimpleButton;
using System.IO;


namespace Library.WebControls.SimpleCheckList {
	[ToolboxBitmap(typeof(SpCheckList), "Library.WebControls.SpCheckList.SpCheckList.bmp")]
	[Designer(typeof(SpCheckListDesign))]
	[SupportsEventValidation]
	[ToolboxData("<{0}:SpCheckList runat=server></{0}:SpCheckList>")]
	[DesignTimeVisible(true)]
	public class SpCheckList : BaseAjaxControl, IEffectControl {
		public SpCheckList() {
			ClientScript = new ClientScript();
			AllText = "All";
			AllValue = AllText;
			AllState = AllItemState.UnCheck;
		}
		public const string CssFile = "spchbl-ui.css";
		private static readonly object EventItemBound = new object();
		private static readonly object EventCustomCallbak = new object();
		protected static readonly Type SpCheckListType = typeof(SpCheckList);
		private bool _isCallback;
		private HtmlGenericNaming _divCombobox;
		private HtmlGenericControl _divTextButtonBox;
		private HtmlGenericControl _divInput;
		private HtmlGenericControl _divContextMenu;
		private HtmlGenericControl _divContextMenuItem;
		private HtmlGenericControl _divContextPanel;
		private HtmlGenericControl _divCheckAllPanel;
		private HtmlGenericControl _spanCheckAllText;


		private CheckBox _chbCheckAll;
		private SpButton _btnClose;
		private WebTextEdit _textCombobox;
		private HiddenField _hfValue;
		private System.Web.UI.WebControls.Image _image;
		protected internal const string CheckListCss = "spCheckList";
		protected internal const string InputImagePanelCss = "chlInputPanel";
		protected internal const string InputImagePanelDisableCss = "chlInputPanelDisable";
		protected internal const string InputPanelCss = "chlInput";
		protected internal const string ContextMenuCss = "chlContextMenu";
		protected internal const string CheckListMenuCss = "chlBoundMenu";
		protected internal const string ContextMenuBtnCss = "chlContextBtn";

		protected const string SpCheckListControlCallbackParameter = "__SPCHECKLISTRQP_";
		protected const string SpCheckListControlCallbaclData = "__SPCHECKLISTRQD_";
		protected const string SpCheckListControlCallbackServerId = "__SPCHECKLISTRQSID_";

		public static bool IsSpCheckListCallback(Page page) {
			return page.Request[SpCheckListControlCallbackParameter] == "T";
		}
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public TextBox TextEdit {
			get {
				EnsureChildControls();
				return _textCombobox;
			}
		}
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public SpButton CloseButton {
			get {
				EnsureChildControls();
				return _btnClose;
			}
		}
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public System.Web.UI.WebControls.Image ImageButton {
			get {
				EnsureChildControls();
				return _image;
			}
		}

		protected override string StyleSheetFileName {
			get {
				return CssFile;
			}
		}


		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			if (Request != null) {
				_isCallback = IsSpCheckListCallback(Page) && Request[SpCheckListControlCallbackServerId] == _divContextMenu.ClientID;

			} else {
				_isCallback = false;
			}
		}
		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);
			IncludeScriptOnLoad(SpCheckListType, "Js", "Library.WebControls.SimpleCheckList.include.SpCheckList.js", UtilLib, EffectLib);

			if (IsCallback) {
				OnCustomCallback(new CustomCallbackEventArgs(GetClientQueryValue(SpCheckListControlCallbaclData)));
			}
		}
		protected virtual void OnCustomCallback(CustomCallbackEventArgs e) {
			var handler = (CustomCallbackEventHandler)Events[EventCustomCallbak];
			if (handler != null) {
				try {
					handler(this, e);
					ProcessCustomCallbackEventArgs(e);
				} catch (Exception ex) {
					WriteError(ex);
				}
			}
		}
		public Unit Width {
			get {
				EnsureChildControls();
				return new Unit(_divTextButtonBox.Style[HtmlTextWriterStyle.Width]);
			}
			set {
				EnsureChildControls();
				_divTextButtonBox.Style[HtmlTextWriterStyle.Width] = value.ToString();
				if (value.Type != UnitType.Percentage)
					_divContextMenu.Style[HtmlTextWriterStyle.Width] = value.ToString();
			}
		}
		public override string ID {
			get {
				EnsureChildControls();
				return _divCombobox.ID;
			}
			set {
				EnsureChildControls();
				_divCombobox.ID = value;
				_textCombobox.ID = "Txt";
				_divContextMenu.ID = "Menu";
				_divContextMenuItem.ID = "Menus";
				_divTextButtonBox.ID = "Panel";
				_hfValue.ID = "Value";
				_btnClose.ID = "Btn";

			}
		}
		public override string ClientID {
			get { return _divCombobox.ClientID; }
		}
		[DefaultValue(200)]
		public Unit MenuHeight {
			get {
				EnsureChildControls();
				return new Unit(_divContextMenuItem.Style[HtmlTextWriterStyle.Height]);
			}
			set {
				EnsureChildControls();
				_divContextMenuItem.Style[HtmlTextWriterStyle.Height] = value.ToString();
			}
		}

		public override bool ClientEnable {
			get {
				return base.ClientEnable;
			}
			set {
				base.ClientEnable = value;
				if (value) {
					_divTextButtonBox.Attributes["class"] = InputImagePanelCss;
				} else {
					_divTextButtonBox.Attributes["class"] = InputImagePanelDisableCss;
				}
			}
		}
		protected override void CreateChildControls() {
			_divCombobox = new HtmlGenericNaming("div");
			_divCombobox.Attributes["class"] = CheckListCss;

			_divTextButtonBox = new HtmlGenericControl("div");
			_divTextButtonBox.Attributes["class"] = InputImagePanelCss;

			_divInput = new HtmlGenericControl("div");
			_divInput.Attributes["class"] = InputPanelCss;

			_divContextMenu = new HtmlGenericControl("div");
			_divContextMenu.Attributes["class"] = CheckListMenuCss;
			_divContextMenu.Style.Add(HtmlTextWriterStyle.Visibility, "hidden");

			_divContextMenuItem = new HtmlGenericControl("Div");
			_divContextMenuItem.Attributes["class"] = ContextMenuCss;

			/////sdfsdfsdfsdf
			_divCheckAllPanel = new HtmlGenericControl("div");
			_divCheckAllPanel.Attributes["class"] = "chlContextCheckAll";
			var spanCheck = new HtmlGenericControl("span");
			spanCheck.Attributes["class"] = "chlMenuItem";

			_chbCheckAll = new CheckBox();
			spanCheck.Controls.Add(_chbCheckAll);
			_divCheckAllPanel.Controls.Add(spanCheck);
			_spanCheckAllText = new HtmlGenericControl("span");
			_spanCheckAllText.Attributes["class"] = "chlItemText";
			_divCheckAllPanel.Controls.Add(_spanCheckAllText);


			_divContextPanel = new HtmlGenericControl("Div");
			_divContextPanel.Attributes["class"] = ContextMenuBtnCss;
			_btnClose = new SpButton();
			_divContextPanel.Controls.Add(_btnClose);

			_textCombobox = new WebTextEdit { AutoCompleteType = AutoCompleteType.None, BackColor = Color.Transparent };

			_hfValue = new HiddenField();
			_divInput.Controls.Add(_textCombobox);
			_divInput.Controls.Add(_hfValue);

			_textCombobox.AutoCompleteType = AutoCompleteType.None;

			_image = new System.Web.UI.WebControls.Image {

				Width = new Unit(16),
				Height = new Unit(16),
				ImageUrl = "~/style/simple/images/navigate_close.png"
			};
			Controls.Add(_divCombobox);
			_divCombobox.Controls.Add(_divTextButtonBox);
			_divCombobox.Controls.Add(_divContextMenu);
			_divContextMenu.Controls.Add(_divContextMenuItem);
			_divContextMenu.Controls.Add(_divCheckAllPanel);
			_divContextMenu.Controls.Add(_divContextPanel);


			_divTextButtonBox.Controls.Add(_divInput);
			_divTextButtonBox.Controls.Add(_image);
		}

		private string _valueSpliter = "|";
		[DefaultValue("|")]
		public string ValueSpliter { get { return _valueSpliter; } set { _valueSpliter = value; } }

		private string _textSpliter = ";";
		[DefaultValue(";")]
		public string TextSpliter { get { return _textSpliter; } set { _textSpliter = value; } }

		public object DataSource { get; set; }
		public string CloseText {
			get {
				EnsureChildControls();
				return _btnClose.Text;
			}
			set {
				EnsureChildControls();
				_btnClose.Text = value;
			}
		}

		public string AllText { get; set; }
		public string AllValue { get; set; }
		public AllItemState AllState { get; set; }

		public string TextField { get; set; }

		public string ValueField { get; set; }
		[DefaultValue(""), PersistenceMode((PersistenceMode.InnerProperty)), Browsable(false), TemplateContainer(typeof(SpCheckListItemTemplate))]
		public ITemplate TextItemTemplate { get; set; }
		public override void DataBind() {
			_divContextMenuItem.Controls.Clear();
			if (DataSource != null) {
				var dsWrapper = new DataSourceWrapper(DataSource);
				int index = 0;
				while (dsWrapper.MoveNext()) {
					//if (index == 0) {
					//  if (AllState != AllItemState.Hidden) {
					//    var allItem = new SpCheckListItemTemplate();
					//    allItem.IsAll = true;

					//    allItem.Value = AllValue;
					//    allItem.Text = AllText;
					//    allItem.CheckList = this;
					//    if (AllState == AllItemState.Checked) {
					//      allItem.Checked = true;
					//      _hfValue.Value = AllValue;
					//      Text = AllText;
					//    }
					//    _divContextMenuItem.Controls.Add(allItem);
					//  }
					//}

					var item = new SpCheckListItemTemplate {
						DataItem = dsWrapper.Current.OriginalItem,
						DataItemIndex = index,
						DisplayIndex = index
					};

					if (!String.IsNullOrEmpty(ValueField)) {
						item.Value = Convert.ToString(dsWrapper.Current.GetPropertyValue(ValueField));
					}
					if (!String.IsNullOrEmpty(TextField)) {
						item.Text = Convert.ToString(dsWrapper.Current.GetPropertyValue(TextField));
					}
					if (TextItemTemplate != null) {
						TextItemTemplate.InstantiateIn(item.TextControl);
					}

					var ev = new SimpleItemBoundEventArgs<SpCheckListItemTemplate>(dsWrapper.Current, item);
					ev.Item.Checked = CheckedValues.Any(s => s == ev.Item.Value);
					ev.Item.CheckList = this;
					var itemBound = (SimpleItemBoundEventHandler<SpCheckListItemTemplate>)Events[EventItemBound];
					if (itemBound != null)
						itemBound(this, ev);
					if (ev.Item.Checked) {
						if (AllState == AllItemState.Checked) {
							_divContextMenuItem.Controls.Clear();
							throw new Exception("Databinding error: Can not check list box item or CheckedValues.Count > 0 when AllState set checked");
						}
						if (_hfValue.Value == "")
							_hfValue.Value = ev.Item.Value;
						else _hfValue.Value += ValueSpliter + ev.Item.Value;
						if (String.IsNullOrEmpty(Text)) {
							Text = ev.Item.Text;
						} else {
							Text = Text + TextSpliter + ev.Item.Text;
						}
					}
					_divContextMenuItem.Controls.Add(ev.Item);
					index++;
				}
			}
			base.DataBind();
		}
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public ClientScript ClientScript {
			private set;
			get;
		}
		public String Text {
			get {
				EnsureChildControls();
				return _textCombobox.Text;
			}
			set {
				EnsureChildControls();
				_textCombobox.Text = value;
			}
		}
		public string[] CheckedValues {
			get {
				EnsureChildControls();
				return _hfValue.Value.Split(new[] { ValueSpliter }, StringSplitOptions.RemoveEmptyEntries);
			}

			set {
				EnsureChildControls();
				Text = String.Empty;
				if (value == null) value = new string[0];
				foreach (SpCheckListItemTemplate control in _divContextMenuItem.Controls) {
					control.Checked = value.Contains(control.Value);
					if (String.IsNullOrEmpty(Text)) {
						Text = control.Text;
					} else {
						Text = Text + TextSpliter + control.Text;
					}
				}
				_hfValue.Value = String.Join(ValueSpliter, value);
			}
		}
		protected override void CreateClientObjectAtRender(HtmlTextWriter writer) {
			BeginScriptTag(writer);
			writer.Write("var {0}=new SpCheckList('{0}','{1}','{2}','{3}',{4},{5},'{6}','{7}','{8}',{9},{10},{11},'{12}', {13});",
				ClientName,
				_divContextMenu.ClientID,
				_hfValue.ClientID,
				_textCombobox.ClientID,
				ClientEnable.ToString().ToLower(),
				ClientVisible.ToString().ToLower(),
				ValueSpliter,
				TextSpliter,
				_divTextButtonBox.ClientID,
				(Int32)DisplayEffect,
				TimeEffect,
				StepEffect,
				_divContextMenuItem.ClientID,
				(Int32)AllState);
			AddScriptHandler(writer, 1, ClientScript.SelectIndexChanged, "AddHandler");
			AddScriptHandler(writer, 2, ClientScript.Shown, "AddHandler");
			EndScriptTag(writer);

		}


		protected override void Render(HtmlTextWriter writer) {
			if (!Visible) return;
			if (TextEdit.ReadOnly || !TextEdit.Enabled) {
				TextEdit.Style.Add(HtmlTextWriterStyle.Cursor, "default");
			}
			if (!_image.Visible) {
				_textCombobox.Width = new Unit(_divContextMenu.Style[HtmlTextWriterStyle.Width]);
			}
			_spanCheckAllText.InnerText = AllText;
			if (AllState == AllItemState.Hidden) {
				_divCheckAllPanel.Visible = false;
			} else if (AllState == AllItemState.Checked) {
				_chbCheckAll.Checked = true;
				Text = AllText;
				_hfValue.Value = AllValue;
			}
			_image.Attributes["onclick"] = ClientName + ".Show()";
			_textCombobox.Attributes["onclick"] = ClientName + ".Show()";
			_textCombobox.Attributes["autocomplete"] = "off";
			_textCombobox.Attributes["onkeypress"] = "return " + ClientName + ".Call(1, event);";
			_chbCheckAll.InputAttributes["onchange"] = ClientName + ".Call(2, this);";
			_chbCheckAll.InputAttributes["_text_"] = AllText;
			_chbCheckAll.InputAttributes["_value_"] = AllValue;
			//KeyPress
			if (String.IsNullOrEmpty(_btnClose.Text)) _btnClose.Text = "Close";
			_btnClose.ClientScript.Click = ClientName + ".Hide();";

			if (IsCallback) {
				WriteCustomCallbackCompleteResult();



				//writer.Write(Text.Length);
				//writer.Write("|");
				//writer.Write(Text);


				var stringWriter = new StringWriter();
				var htmlTextWriter = new HtmlTextWriter(stringWriter);
				foreach (Control ctr in _divContextMenuItem.Controls) {
					ctr.RenderControl(htmlTextWriter);
				}

				var resultText = ConvertToArrayString(_hfValue.Value, Text, stringWriter.ToString());
				writer.Write(resultText);
				FlushAndEndCallback();
			} else {
				base.Render(writer);
			}
		}

		public override bool IsCallback {
			get { return _isCallback; }
		}
		public event SimpleItemBoundEventHandler<SpCheckListItemTemplate> ItemBound {
			remove {
				Events.RemoveHandler(EventItemBound, value);
			}
			add {
				Events.AddHandler(EventItemBound, value);
			}
		}
		public event CustomCallbackEventHandler CustomCallback {
			remove {
				Events.RemoveHandler(EventCustomCallbak, value);
			}
			add {
				Events.AddHandler(EventCustomCallbak, value);
			}
		}

		#region Implementation of IEffectControl

		public Effect DisplayEffect {
			get;
			set;
		}

		public int TimeEffect {
			get;
			set;
		}

		public int StepEffect {
			get;
			set;
		}

		#endregion
	}
}
